package com.af.monitorModule.controller.websocket;

import com.af.monitorModule.generator.mapper.CompanyMapper;
import com.af.monitorModule.generator.mapper.TimedTaskResultMapper;
import com.af.monitorModule.generator.service.ServerPushService;
import com.af.monitorModule.generator.service.ServerService;
import com.af.monitorModule.util.RestUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import javax.websocket.*;
import javax.websocket.server.ServerEndpoint;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.CopyOnWriteArraySet;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @author lyz
 */
@ServerEndpoint(value = "/ws/problems")
@Component
public class ProblemsSocket {

    private static final Logger logger = LoggerFactory.getLogger(ProblemsSocket.class);

    private static final AtomicInteger ON_LINE_COUNT = new AtomicInteger(0);

    private static final CopyOnWriteArraySet<Session> SESSION_SET = new CopyOnWriteArraySet<>();




    /**
     * 调用时Top3会报错，所以全部查出来，在java里截取
     */
    private static final String sql1 = "select a.f_project,sum(b.num) as num from t_new_sales a left join (\n" +
            "\tselect f_sales_id,sum(f_count) as num from t_new_question\n" +
            "\tgroup by f_sales_id) b on a.id = b.f_sales_id\n" +
            "\twhere a.f_checkin_time > dateadd( DAY,- 7, CONVERT ( VARCHAR ( 10 ), GETDATE( ), 120 ) ) \n" +
            "\tgroup by a.f_project\n" +
            "\torder by sum(b.num) desc";

    private static final String sql2 = "select f_problemtype as name,sum(f_count) as value from t_new_question where f_sales_id in(\n" +
            "\tselect id from t_new_sales \n" +
            "\twhere f_project = '{}' and f_checkin_time > DATEADD( DAY,- 7, CONVERT ( VARCHAR ( 10 ), GETDATE( ), 120 ) ) )\n" +
            "\tgroup by f_problemtype\n" +
            "\torder by sum(f_count) desc";

    private static final String sql3 = "select f_type from t_new_sales where f_checkin_time > dateadd( DAY,- 7, CONVERT ( VARCHAR ( 10 ), GETDATE( ), 120 ) )";

    private static final String sql4 = "select a.f_applicant  as name ,sum(b.num) as value from t_new_sales a\n" +
            "left join (\n" +
            "select f_sales_id,sum(isnull(f_count,0)) as num from t_new_question group by f_sales_id\n" +
            ") b on a.id = b.f_sales_id\n" +
            "where a.f_checkin_time > dateadd( DAY,- 7, CONVERT ( VARCHAR ( 10 ), GETDATE( ), 120 ) )\n" +
            "group by a.f_applicant\n" +
            "order by sum(b.num) desc";

    /**
     * 连接建立成功调用的方法
     */
    @OnOpen
    public void onOpen(Session session) {
        SESSION_SET.add(session);
        int cnt = ON_LINE_COUNT.incrementAndGet();
        logger.info("有连接加入，id={}，当前连接数为：{}", session.getId(), cnt);
    }

    /**
     * 连接关闭调用的方法
     */
    @OnClose
    public void onClose(Session session) {
        SESSION_SET.remove(session);
        int cnt = ON_LINE_COUNT.decrementAndGet();
        logger.info("有连接关闭，当前连接数为：{}", cnt);
    }

    /**
     * 收到客户端消息后调用的方法
     *
     * @param message
     *            客户端发送过来的消息
     */
    @OnMessage
    public void onMessage(String message, Session session) {
    }

    /**
     * 出现错误
     */
    @OnError
    public void onError(Session session, Throwable error) {
        logger.error("发生错误：{}，Session ID： {}",error.getMessage(),session.getId());
        logger.error("info is ", error);
    }


    /**
     * 发送消息，实践表明，每次浏览器刷新，session会发生变化。
     */
    public static void sendMessage(Session session, String message) {
        session.getAsyncRemote().sendText(message);
    }

    /**
     * 群发消息
     */
    public static void broadCastInfo(String message){
        for (Session session : SESSION_SET) {
            if(session.isOpen()){
                sendMessage(session, message);
            }
        }
    }

    /**
     * 指定Session发送消息
     */
    public static void sendMessage(String message,String sessionId){
        Session session = null;
        for (Session s : SESSION_SET) {
            if(s.getId().equals(sessionId)){
                session = s;
                break;
            }
        }
        if(session!=null){
            sendMessage(session, message);
        }
        else{
            logger.warn("没有找到你指定ID的会话：{}",sessionId);
        }
    }



    @Scheduled(cron = "0/10 * * * * ? ")
    public void need2Send(){
        long start = System.currentTimeMillis();
        //开始获取
        JSONArray objects = runOaSql(sql1);
        JSONArray top3 = new JSONArray();
        for (int i = 0; i < 3; i++) {
            JSONObject one = objects.getJSONObject(i);
            JSONArray details = runOaSql(sql2.replace("{}", one.getString("f_project")));
            one.put("details",details);
            top3.add(one);
        }
        objects = runOaSql(sql3);
        JSONObject times = new JSONObject();
        for (int i = 0; i < objects.size(); i++) {
            String[] one = objects.getJSONObject(i).getString("f_type").replace("[\"","").replace("\"]","").split(",");
            for (String s : one) {
                times.put(s, times.containsKey(s) ? times.getIntValue(s) + 1 : 1);
            }
        }
        JSONArray count = new JSONArray();
        times.forEach((k,v) ->{
            count.add(new JSONObject(){{put("name",k);put("value",v);}});
        });
        JSONArray people = runOaSql(sql4);

        JSONObject resData = new JSONObject() {{
            put("top3", top3);
            put("count", count);
            put("people", people);
        }};
        System.out.println(resData.toJSONString());
        broadCastInfo(resData.toJSONString());
    }


    public JSONArray runOaSql(final String sql){
        return RestUtil.sendPost("http://121.36.59.193:8081/oa-1.0.2/rs/sql/run_sql_result", JSONArray.class, new HashMap() {{
            put("data", new HashMap<String,String>() {{
                put("run_sql", sql);
            }});
        }});
    }

}
